#!/bin/bash
# Autor:        Saúl Martínez Vidals
# Fecha:        lun 22 oct 2007
# Descripción:  Envío de mensajes remotos a las máquinas seleccionadas


# # # # # # # #      D E F I N I C I O N    D E    F U N C I O N E S      # # # # # # # #
# verifica que las herramientas necesarias esten instaladas en el equipo
function verifica_herramientas
{
    # dirección de los binarios de los comandos
    dsh="/bin/ls"
    zenity="/usr/bin/zenity"

    # chequeo de la existencia  de las herramientas
    if [ ! -x "$zenity" ]; then
        echo "Para el funcionamiento de este script es necesario instalar zenity"
        return 1
    elif [ ! -x "$dsh" ]; then
        zenity --error \
               --text="Para el funcionamiento de este script es necesario instalar dsh"
        return 1
    else
        return 0
    fi
}


# manual
function manual
{
    declare -a in=("\e[1;37m" "\e[1;32m" "\e[1;34m" "\e[1;36m")
    declare fin="\e[0m"
    declare uso=""

    uso+="${in[0]}SINOPSIS: $fin\n"
    uso+="\t${in[3]}mensajes $fin[${in[1]} accion $fin] [${in[2]} opciones... $fin]\n\n"
    uso+="${in[0]}DESCRIPCION: $fin\n"
    uso+="\tEnvía mensajes a las máquinas seleccionadas, si no se especifica una acción s"
    uso+="ólo se despliega el texto.\n\n"
    uso+="${in[0]}ACCIONES:$fin -${in[0]}[$fin\aacr${in[0]}]$fin\n"
    uso+="\t-a, --apagar\t${in[1]}*$fin Apagar el equipo\n"
    uso+="\t-c, --cerrar\t${in[1]}*$fin Cerrar sesión\n"
    uso+="\t-r, --reiniciar\t${in[1]}*$fin Reiniciar el equipo\n\n"
    uso+="${in[0]}OPCIONES:$fin -${in[0]}[$fin\atT${in[0]}]$fin\n"
    uso+="\t-t ${in[2]}<numero>$fin\t${in[1]}*$fin Tiempo de espera antes de ejecutar la "
    uso+="acción (en minutos)\n"
    uso+="\t-T ${in[2]}<texto>$fin\t${in[1]}*$fin Texto en el diálogo\n"

    # imprime en pantalla el manual
    echo -e "$uso"
}


# verifica que los argumentos recibidos sean válidos
function verifica_argumentos
{
    # si no hay argumentos se detiene la ejecución del script
    if [ $# -gt 0 ]; then
        # verifica la acción a ejecutar
        case "$1" in
            -a | --apagar)      accion="-a"
                                shift
                                ;;
            -c | --cerrar)      accion="-c"
                                shift
                                ;;
            -r | --reiniciar)   accion="-c"
                                shift
                                ;;
        esac

        # analiza las opciones recibidas
        declare -i k=0
        while [ $# -gt 0 ]; do
            case "$1" in
                # opción para especificar el tiempo de espera
                -t) shift
                    # debe estar especificado el numero 
                    if [ "$1" ]; then
                        opciones[$k]="-t"
                        opciones[$k+1]="$1"
                        k=$k+2
                    else
                        echo -e "Es necesario un número entero después de la opción -t"
                    fi
                    ;;
                # opción para especificar texto
                -T) shift
                    # cadena de texto con el texto a desplegar
                    if [ "$1" ]; then
                        opciones[$k]="-T"
                        opciones[$k+1]="$1"
                        k=$k+2
                    else
                        echo -e "Es necesaria una cadena de texto desoués de la opción -T"
                    fi
                    ;;
                *)  echo -e "argumento no válido: $1\n\n"
                    manual
                    exit 1
                    ;;
            esac
            shift
        done
    else
        manual
        exit 1
    fi
}


# busca las máquinas encendidas
# Valores regresados:
# 1: Si hubo un error o no hay máquinas encendidas
# 0: Si todo sale bien
function busca_encendidas
{
    cat encendidas > $encendidas
    return 0
}


# despliega en pantalla la lista de las máquinas encendidas
function lista
{
    # datos de la venatana
    declare -a columnas=("Activar" "Nombre" "IP")
    declare -i ancho=300
    declare -i alto=500
    declare icono="/usr/share/pixmaps/vl_2_32.png"
    declare texto="Selecciona las maquinas:"
    declare titulo="Envío de mensajes"

    # despliega la lista
    zenity  --title="$titulo" \
            --text="$texto" \
            --width=$ancho --height=$alto \
            --window-icon=$icono \
            --list --checklist \
            --column=${columnas[0]} --column=${columnas[1]} --column=${columnas[2]} \
            --separator=" " $(cat $encendidas) > $receptoras 2> /dev/null
    return $?
}


# envío de mensaje a una máquina
function mensaje
{
    declare -a mensaje=(
                "El equipo "
                " automáticamente en "
                " minutos, respalda tus "
                "archivos, el laboratorio no se hace responsable por la perdida de datos."
                )
    declare -a instruccion
    declare mensaje_tmp
    declare titulo

    # minutos a esperar antes de que el equipo se apague, si no se recibe ningún numero -
    # como parámetro, por defecto toma el valor de 0
    declare -i minutos=0

    if [ $2 ]; then
        minutos=$2
    fi

    # instrucción a ejecutar
    instruccion[0]="sleep $minutos"
    instruccion[0]+="m"

    # usa el servidor X de la máquina remota
    export DISPLAY=:0.0

    case "$1" in
        "-a")   mensaje_tmp="se apagará"
                titulo="Aviso importante"
                instruccion[1]="poweroff"
                ;;
        "-c")   mensaje_tmp="cerrara sesión"
                titulo="Aviso importante"
                instruccion[1]="gnome-session-save --kill --silent"
                ;;
        "-r")   mensaje_tmp="se reiniciará"
                titulo="Aviso importante"
                instruccion[1]="reboot"
                ;;
    esac

    # crea el mensaje
    if [ "$3" ]; then
        mensaje[0]="$3"
    else
        mensaje[0]+="$mensaje_tmp"
        mensaje[0]+="${mensaje[1]}"
        mensaje[0]+="$minutos"
        mensaje[0]+="${mensaje[2]}"
        mensaje[0]+="${mensaje[3]}"
    fi

    zenity  --info \
            --text="${mensaje[0]}" \
            --title="$titulo" 2> /dev/null

    # instrucción a ejecutar
    ${instruccion[0]}&
    ${instruccion[1]}
}


# envía los mensajes a las máquinas seleccionadas
function envia_mensajes
{
    declare -ix  contador=1
    declare -i i=0
    declare -i minutos
    declare texto

    # cuenta el número de máquinas receptoras
    for i in $(cat $receptoras); do ((contador++)); done

    # analiza las opciones recibidas
    while [ $i -lt ${#opciones[*]} ]; do
        case "${opciones[$i]}" in
            "-t")   minutos=${opciones[i+1]}
                    ;;
            "-T")   texto="${opciones[i+1]}"
                    ;;
        esac
        i=$i+2
    done

    # envía el mensaje a las máquinas
    echo "mensaje $accion $minutos $texto"
    mensaje $accion $minutos "$texto"

    zenity --info --title="$titulo" --text="$contador mensajes enviados" 2> /dev/null
}



# # # # # # # # # #      V A R I A B L E S      G L O B A L E S      # # # # # # # # # #
# acciones y opciones válidas
declare -a acciones=("-a" "--apagar" "-c" "--cerrar" "-r" "--reiniciar")
declare -a opciones=("-t" "-T")

# archivos temporales
declare encendidas=$(mktemp -t)
declare receptoras=$(mktemp -t)

# accion y opciones recibidas como parámetros
declare accion=""
declare -a opciones

# verifica que las herramientas necesarias esten instaladas
verifica_herramientas || exit 1

# verifica los parametros recibidos
verifica_argumentos "$@" || exit 1

# busca las máquinas encendidas
busca_encendidas

# si hay máquinas encendidas sigue adelante, en caso contrario finaliza la ejecución
if [ $? -eq 0 ]; then
    # despliega la lista para seleccionar a las máquinas receptoras
    lista

    # llamado a la función que envía los mensajes
    if [ $? -eq 0 ]; then
        envia_mensajes
    fi
else
    zenity  --warning --text="Ningún equipo esta encendido"
fi

# elimina los archivos creados
rm $encendidas $receptoras

exit 0
